﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Linq.Expressions;
using OpenWaves.Collections;

namespace OpenWaves.ActivityFeed.NHibernate
{
    public static class UpdateExtensions
    {
        public static IQueryable<Update> ForSubscriber(this IQueryable<Update> query, Subscriber subscriber)
        {
            Contract.Requires<ArgumentNullException>(subscriber != null);

            var followedTopics = subscriber.Subscriptions.Select(s => s.Name).ToList();
            query = query.Where(update => update.PublishedBy == subscriber.Id || update.Topics.Any(t => followedTopics.Contains(t.Name)));

            return query;
        }

        public static IQueryable<Update> FilterByTopics(this IQueryable<Update> query, params Topic[] topics)
        {
            Contract.Requires<ArgumentNullException>(topics != null);

            return query.FilterByTopics(topics.AsEnumerable());
        }

        public static IQueryable<Update> FilterByTopics(this IQueryable<Update> query, IEnumerable<Topic> topics)
        {
            Contract.Requires<ArgumentNullException>(topics != null);

            var topicNames = topics.Select(t => t.Name).ToList();

            if (topicNames.IsEmpty())
                return query;

            return query.Where(u => u.Topics.Any(t => topicNames.Contains(t.Name)));            
        }

        public static IQueryable<Update> SecurityTrim(this IQueryable<Update> query, IEnumerable<UserGroup> userGroups)
        {
            Contract.Requires<ArgumentNullException>(userGroups != null);

            var userGroupsNames = userGroups.Select(u => u.Name).ToList();

            return query.Where(u => u.IsPublic || u.UserGroups.Any(group => userGroupsNames.Contains(group.Name)));
        }           
    }     
}